package hu.sed.stud.demo10.persistence;

import java.io.Serializable;
import java.util.List;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;

/**
 * Generic Data Access Object implementation. Do not implement it directly.
 * @param <T> Type you want to access
 * @param <ID> Type you want to use as id
 */
public interface GenericDao<T, ID extends Serializable> {


	/**
	 * Find an entity by id.
	 * 
	 * @param id by id
	 * @param lock can be lock
	 * @return the entity if it exists, null if not
	 */
	public T findById(ID id, boolean lock);

	/**
	 * Find a list contains entities by an examples instance, exclude the exclude properties.
	 * 
	 * @param exampleInstance by the example instance
	 * @param excludeProperty exclude properties list
	 * @return the entity list
	 */
	public List<T> findByPost(T examplePost, String[] excludeProperty);

	/**
	 * Make persistent a T type entity.
	 * 
	 * @param entity the entity
	 * @return the persisted entity
	 */
	public T makePersistent(T entity);

	/**
	 * Save an entity immediately into to the datastore, no matter its in or out of the transaction.
	 * 
	 * @param entity the entity be saved
	 * @return the saved entity identify
	 */
	public ID save(T entity);

	/**
	 * Make persistent an entity if it wasn't and update immediately.
	 * 
	 * @param entity the entity be updated
	 */
	public void update(T entity);

	/**
	 * Make a transient instance persistent.
	 * 
	 * @param entity a transient instance to be made persistent
	 */
	public void persist(T entity);

	/**
	 * Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently
	 * associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and
	 * return it as a newly persistent instance. The given instance does not become associated with the session
	 * 
	 * @param entity a detached instance with state to be copied
	 * @return an updated persistent instance
	 */
	public T merge(T entity);

	/**
	 * Delete an entity from the datastore.
	 * 
	 * @param entity the entity will be deleted
	 */
	public void makeTransient(T entity);

	/**
	 * This method says that the entity is transient.
	 * 
	 * @param entity the entity will be queried
	 * @return true if the entity is not persistent, namely transient
	 */
	public boolean isTransient(final T entity);

	/**
	 * This method says that the entity is persistent.
	 * 
	 * @param entity the entity will be queried
	 * @return true if the entity is persistent, namely not transient
	 */
	public boolean isPersistent(final T entity);

	/**
	 * Force this hibernate session to flush. Must be called at the end of a unit of work, before commiting the transaction and closing the
	 * session.
	 */
	public void flush();

	/**
	 * Completely clear the hibernate session.
	 */
	public void clear();

	/**
	 * Remove this instance from the session cache. Changes to the instance will not be synchronized with the database. This operation
	 * cascades to associated instances if the association is mapped with cascade="evict".
	 * 
	 * @param entity a persistent instance
	 */
	public void evict(T entity);

	/**
	 * Find entities by a criteria.
	 * 
	 * @param criterion the restrictions, projections, etc
	 * @return the list of the entities
	 */
	public List<T> findByCriteria(Criterion... criterion);

	/**
	 * Find and order entities by a criteria.
	 * 
	 * @param criterion
	 * @param order
	 * @return
	 */
	public List<T> findByCriteria(Criterion[] criterion, Order[] order);

	// TODO norm�lis javadoc
	/**
	 * Session flush, session clear. Find entities by a criteria.
	 * 
	 * @param criterion the restrictions, projections, etc
	 * @return the list of the entities
	 */
	public List<T> findByCriteriaAfterClear(final Criterion... criterion);

	/**
	 * Find entities by a criteria. Every entity performs once.
	 * 
	 * @param criterion the restrictions, projections, etc
	 * @return the list of the entities
	 */
	public List<T> findByDistinctCriteria(Criterion... criterion);

	/**
	 * Find entities by a criteria. Every entity performs once and it can a pageable query.
	 * 
	 * @param page the begin page
	 * @param itemsPerPage count of items per page
	 * @param criterion the restrictions, projections, etc
	 * @return the list of the entities
	 */
	public List<T> findByDistinctPageableCriteria(final int page, final int itemsPerPage, final Criterion... criterion);

	/**
	 * Give the count of distinct items by criteria.
	 * 
	 * @param criterion the criterions
	 * @return count of items
	 */
	public long countByDistinctCriteria(final Criterion... criterion);

	/**
	 * Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement long-running
	 * sessions that span many business tasks.
	 * 
	 * @param object
	 */
	public void refresh(final Object object);
	
}
